﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;


namespace Teal.Compiler {

    /// <summary>
    /// 支持从 .net 程序集导入类库。
    /// </summary>
    public static class AssemblyImporter {

        /// <summary>
        /// 已导入的程序集。
        /// </summary>
        private static Dictionary<Assembly, NamespaceReference> _importedAssemblies;

        /// <summary>
        /// 导入一个模块的所有成员。
        /// </summary>
        /// <param name="target"></param>
        public static void import(ModuleReference target) {

            // 导入所有依赖库。
            _importedAssemblies = new Dictionary<Assembly, NamespaceReference>(Compiler.options.importedLibs.Count * 2);
            foreach (var lib in Compiler.options.importedLibs) {
                var assembly = loadAssembly(lib.path);
                if (assembly == null) {
                    continue;
                }
                _importedAssemblies[assembly] = createNamespace(target, lib.alias);
            }

            // 载入系统类型。
            importPredefinedTypes(target);

            // 导入所有类型。
            foreach (var vk in _importedAssemblies) {
                importAssembly(vk.Key, vk.Value);
            }

        }

        /// <summary>
        /// 创建指定的命名空间。
        /// </summary>
        /// <param name="target"></param>
        /// <param name="ns"></param>
        /// <returns></returns>
        private static NamespaceReference createNamespace(NamespaceReference target, string ns) {
            if (ns != null) {
                foreach (var name in ns.Split('.')) {
                    var found = target.getMember(name);
                    var t = found as NamespaceReference;
                    if (t == null) {

                        // 发现了成员，但它不是命名空间。
                        if (found != null) {

                            // todo: 如何处理？

                            //while ((found = found.next) != null) {
                            //    if ((t = found as NamespaceReference) != null) {
                            //        goto foundCurrent;
                            //    }
                            //}

                            t = new NamespaceReference();
                            t.name = name;
                            goto foundCurrent;
                        }

                        t = new NamespaceReference();
                        t.name = name;
                        target.addMember(t);
                    }
                foundCurrent:
                    target = t;
                }
            }
            return target;
        }

        /// <summary>
        /// 载入指定路径的程序集。
        /// </summary>
        /// <param name="assemblyFile"></param>
        /// <param name="target"></param>
        public static Assembly loadAssembly(string assemblyFile) {
            try {
                return Assembly.LoadFile(assemblyFile);
            } catch (FileNotFoundException) {
                Compiler.error(ErrorCode.none, String.Format("无法加载依赖项“{0}”；找不到文件", assemblyFile));
            } catch (BadImageFormatException e) {
                Compiler.error(ErrorCode.none, String.Format("无法加载依赖项“{0}”；{1}", assemblyFile, e.Message));
            }
            return null;
        }

        /// <summary>
        /// 载入指定的程序集。
        /// </summary>
        /// <param name="assemblyFile"></param>
        /// <param name="container"></param>
        public static void importAssembly(Assembly assembly, NamespaceReference container) {

            // 忽略所有导入错误。
            // 在实际使用时才会报告错误。
            Type[] types;
            try {
                types = assembly.GetTypes();
            } catch (ReflectionTypeLoadException e) {
                types = e.Types;
            }

            string currentNsString = null;
            NamespaceReference currentNsReference = container;
            foreach (var t in types) {

                // 不载入无法加载的类型。
                if (t == null)
                    continue;

                // 不载入内嵌类型。
                if (t.MemberType == MemberTypes.NestedType)
                    continue;

                // 更新导入的命名空间。
                if (currentNsString != t.Namespace) {
                    currentNsString = t.Namespace;
                    currentNsReference = createNamespace(container, currentNsString);
                }

                // 正式导入类型。
                importType(t, currentNsReference);
            }
        }

        private static readonly Dictionary<Type, TypeReference> _importedTypes = new Dictionary<Type, TypeReference>(128);

        /// <summary>
        /// 导入一个类型。
        /// </summary>
        /// <param name="metaInfo">成员的原始信息。</param>
        /// <returns></returns>
        public static TypeReference importType(Type metaInfo, NamespaceReference container = null) {

            // 不重复载入。
            TypeReference result;
            if (_importedTypes.TryGetValue(metaInfo, out result)) {
                return result;
            }

            // 不载入生成类型。
            if (isCompilerGenerated(metaInfo)) {
                return null;
            }

            // 泛型必须通过泛型定义导入。
            if (metaInfo.IsGenericType && !metaInfo.IsGenericTypeDefinition) {
                // 导入其定义类型。
                var def = importType(metaInfo.GetGenericTypeDefinition());
                int index = 0;
                return importGenericType(def, metaInfo.GetGenericArguments(), ref index);
            }

            // 类型可能是：
            //     Type
            //     Array<Type>
            //     Ptr<Type>
            //     Ref<Type>
            //     Type<>  ->  GenericTypeDefinitionReference
            //     Type<Type>  ->  GenericTypeReference
            //     Type<>.Type  ->  TypeReference
            //     Type<>.Type<>  ->  GenericTypeDefinitionReference
            //     Type<>.Type<Type>  ->  GenericTypeReference
            //     Type<Type>.Type  ->  GenericTypeReference
            //     Type<Type>.Type<>  ->  GenericTypeReference
            //     Type<Type>.Type<Type>  ->  GenericTypeReference

            if (metaInfo.IsGenericType) {
                // 载入泛型定义本身。
                int tparamsCount = metaInfo.DeclaringType == null ? 0 : metaInfo.DeclaringType.GetGenericArguments().Length;
                tparamsCount = metaInfo.GetGenericArguments().Length - tparamsCount;
                if (tparamsCount == 0) {
                    result = new ImportedTypeReference(getMemberType(metaInfo));
                } else {
                    result = new ImportedGenericTypeDefinitionReference(getMemberType(metaInfo));
                }
            } else if (metaInfo.HasElementType) {
                var element = importType(metaInfo.GetElementType());
                if (metaInfo.IsArray) {
                    result = PredefinedTypes.System_Array_T.makeGenericType(element);
                } else if (metaInfo.IsPointer) {
                    result = PredefinedTypes.System_Ptr_T.makeGenericType(element);
                } else if (metaInfo.IsByRef) {
                    result = PredefinedTypes.System_Ref_T.makeGenericType(element);
                } else {
                    throw new Unreachable();
                }
            } else {
                // 载入非泛型。
                result = new ImportedTypeReference(getMemberType(metaInfo));
            }

            var ma = metaInfo.Attributes;
            switch (ma & TypeAttributes.VisibilityMask) {
                case TypeAttributes.Public:
                case TypeAttributes.NestedPublic:
                    result.modifiers = Modifiers.@public;
                    break;
                case TypeAttributes.NestedPrivate:
                    result.modifiers = Modifiers.@private;
                    break;
                case TypeAttributes.NestedFamily:
                case TypeAttributes.NestedFamORAssem:
                    result.modifiers = Modifiers.@protected;
                    break;
            }

            if ((ma & TypeAttributes.Sealed) != 0) {
                if ((ma & TypeAttributes.Abstract) != 0)
                    result.modifiers |= Modifiers.@static;
                else
                    result.modifiers |= Modifiers.final;
            } else if ((ma & TypeAttributes.Abstract) != 0) {
                result.modifiers |= Modifiers.@abstract;
            }

            _importedTypes[metaInfo] = result;
            result.name = getMemberName(metaInfo.Name);
            result.metaInfo = metaInfo;

            // 自动识别命名空间。
            if (container == null) {
                // 如果是内嵌类型，必须先导入容器类型。
                if (metaInfo.MemberType == MemberTypes.NestedType) {
                    container = importType(metaInfo.DeclaringType);
                } else {
                    if (!_importedAssemblies.TryGetValue(metaInfo.Assembly, out container)) {
                        container = Compiler.currentModule.reference;
                    }
                    container = createNamespace(container, metaInfo.Namespace);
                }
            }

            container.addMember(result);

            if (metaInfo.BaseType != null) {
                result.baseClass = importType(metaInfo.BaseType);
            }

            var it = metaInfo.GetInterfaces();
            if (it.Length > 0) {
                var baseInterfaces = new List<TypeReference>(it.Length);
                for (int i = 0; i < it.Length; i++) {
                    baseInterfaces.Add(importType(it[i]));
                }
                result.baseInterfaces = baseInterfaces;
            }

            return result;
        }

        /// <summary>
        /// 导入一个泛型类。
        /// </summary>
        /// <param name="definitionType">泛型定义类。</param>
        /// <param name="targs">泛型参数列表。</param>
        /// <param name="argIndex">当前泛型参数位置。</param>
        /// <returns>生成的泛型类。</returns>
        private static TypeReference importGenericType(TypeReference definitionType, Type[] targs, ref int argIndex) {

            var tparamCount = definitionType.genericParameterCount;

            // 父类型如果是泛型，则更新当前成员为父类型的泛型内嵌类。
            var p = definitionType.containerType;
            if (p != null) {
                definitionType = (TypeReference)importGenericType(p, targs, ref argIndex).getMember(definitionType.name, tparamCount);
            }

            // 如果父类是泛型，则生成其泛型实例。
            if (tparamCount > 0) {
                var types = new TypeReference[tparamCount];
                for (int i = 0; i < tparamCount; i++) {
                    types[i] = importType(targs[argIndex + i]);
                }
                definitionType = ((GenericTypeDefinitionReference)definitionType).makeGenericType(types);
                argIndex += tparamCount;
            }

            return definitionType;

        }

        private static MemberReference.GenericParameter importGenericParameter(Type metaInfo) {
            Debug.Assert(metaInfo.IsGenericParameter);
            var result = new MemberReference.GenericParameter();
            result.name = metaInfo.Name;
            result.baseClass = PredefinedTypes.System_Object;
            var gpc = metaInfo.GetGenericParameterConstraints();
            if (gpc.Length > 0) {
                result.baseInterfaces = new List<TypeReference>(gpc.Length);
                for (int j = 0; j < gpc.Length; j++) {
                    result.baseInterfaces.Add(importType(gpc[j]));
                }
            }
            return result;
        }

        private static MemberType getMemberType(Type metaInfo) {
            return metaInfo.IsValueType ? MemberType.@struct :
                metaInfo.IsEnum ? MemberType.@enum :
                metaInfo.IsInterface ? MemberType.@interface :
                MemberType.@class;
        }

        public static TypeReference[] importGenericArguments(MemberInfo metaInfo, Type[] genericArguments) {
            var first = metaInfo.DeclaringType == null ? 0 : metaInfo.DeclaringType.GetGenericArguments().Length;
            var result = new TypeReference[genericArguments.Length - first];
            for (int i = 0; i < result.Length; i++) {
                result[i] = importType(genericArguments[first + i]);
            }
            return result;
        }

        public static TypeReference[] importGenericArguments(Type[] genericArguments) {
            var result = new TypeReference[genericArguments.Length];
            for (int i = 0; i < result.Length; i++) {
                result[i] = importType(genericArguments[i]);
            }
            return result;
        }

        public static MemberReference.GenericParameter[] importGenericParameters(MemberInfo metaInfo, Type[] genericParameters) {
            var first = metaInfo.DeclaringType == null ? 0 : metaInfo.DeclaringType.GetGenericArguments().Length;
            if (genericParameters.Length == first) {
                return null;
            }
            var result = new MemberReference.GenericParameter[genericParameters.Length - first];
            for (int i = first; i < genericParameters.Length; ++i) {
                var gp = importGenericParameter(genericParameters[i]);
                gp.index = i - first;
                result[gp.index] = gp;
            }
            return result;
        }

        /// <summary>
        /// 导入指定类型的实际子成员。
        /// </summary>
        /// <param name="target"></param>
        public static void importMembers(TypeReference target) {
            var ms = target.metaInfo.GetMembers();
            target.members = new Dictionary<string, MemberReference>(ms.Length);
            foreach (var m in ms) {
                importMember(m, target);
            }
        }

        /// <summary>
        /// 导入指定类型的成员。
        /// </summary>
        /// <param name="metaInfo">成员的原始信息。</param>
        /// <returns></returns>
        public static MemberReference importMember(MemberInfo metaInfo, NamespaceReference container) {
            switch (metaInfo.MemberType) {
                case MemberTypes.TypeInfo:
                case MemberTypes.NestedType:
                    return importType((Type)metaInfo, container);
                case MemberTypes.Method:
                    return importMethod((MethodInfo)metaInfo, container);
                case MemberTypes.Field:
                    return importField((FieldInfo)metaInfo, container);
                case MemberTypes.Property:
                    return importProperty((PropertyInfo)metaInfo, container);
                case MemberTypes.Event:
                    return importEvent((EventInfo)metaInfo, container);
                case MemberTypes.Constructor:
                    return importConstructor((ConstructorInfo)metaInfo, container);
                default:
                    return null;
            }
        }

        /// <summary>
        /// 导入一个字段信息。
        /// </summary>
        /// <param name="metaInfo">成员的原始信息。</param>
        /// <returns></returns>
        private static FieldReference importField(FieldInfo metaInfo, NamespaceReference container) {

            Modifiers modifiers;

            // 处理修饰符。
            var fa = metaInfo.Attributes;
            switch (fa & FieldAttributes.FieldAccessMask) {
                case FieldAttributes.Public:
                case FieldAttributes.Assembly:
                    modifiers = Modifiers.@public;
                    break;
                case FieldAttributes.Family:
                case FieldAttributes.FamORAssem:
                    modifiers = Modifiers.@protected;
                    break;
                default:
                    // 忽略私有字段。
                    return null;
            }

            // 忽略编译器自动生成字段。
            if (isCompilerGenerated(metaInfo)) {
                return null;
            }

            var result = new FieldReference();
            if ((fa & FieldAttributes.Literal) != 0) {
                modifiers |= Modifiers.@const;

                var constVal = metaInfo.GetRawConstantValue();

                // 载入常量。


                //Constant c = field_type.Kind == MemberKind.MissingType ?
                //    new NullConstant(InternalType.ErrorType, Location2.Null) :
                //    Constant.CreateConstantFromValue(field_type, metaInfo.GetRawConstantValue(), Location2.Null);
                //return new ConstSpec(declaringType, definition, field_type, metaInfo, modifiers, c);

            } else {
                if ((fa & FieldAttributes.InitOnly) != 0) {
                    modifiers |= Modifiers.final;
                } else if (Array.IndexOf(metaInfo.GetRequiredCustomModifiers(), typeof(IsVolatile)) >= 0) {
                    modifiers |= Modifiers.@volatile;
                }

                if ((fa & FieldAttributes.Static) != 0) {
                    modifiers |= Modifiers.@static;
                }
            }

            result.modifiers = modifiers;
            result.name = metaInfo.Name;
            result.metaInfo = metaInfo;
            container.addMember(result);

            result.returnType = importType(metaInfo.FieldType);
            return result;
        }

        /// <summary>
        /// 载入指定类型的元数据。
        /// </summary>
        /// <param name="metaInfo">成员的原始信息。</param>
        /// <returns></returns>
        private static FieldReference importEvent(EventInfo metaInfo, NamespaceReference container) {
            var result = new FieldReference();

            if ((metaInfo.AddMethod.Attributes & MethodAttributes.Static) != 0) {
                result.modifiers |= Modifiers.@static;
            }

            result.name = metaInfo.Name;
            ((MemberReference)result).metaInfo = metaInfo;
            container.addMember(result);

            result.returnType = importType(metaInfo.EventHandlerType);

            return result;
        }

        private static MethodReference importConstructor(ConstructorInfo metaInfo, NamespaceReference container) {
            return importMethod(metaInfo, container);
        }

        private static MethodReference importMethod(MethodBase metaInfo, NamespaceReference container) {

            // 读取修饰符。
            Modifiers modifiers;
            var ma = metaInfo.Attributes;
            switch (ma & MethodAttributes.MemberAccessMask) {
                case MethodAttributes.Public:
                case MethodAttributes.Assembly:
                    modifiers = Modifiers.@public;
                    break;
                case MethodAttributes.Family:
                case MethodAttributes.FamORAssem:
                    modifiers = Modifiers.@protected;
                    break;
                default:
                    return null;
            }

            if (isCompilerGenerated(metaInfo)) {
                return null;
            }

            if ((ma & MethodAttributes.Static) != 0) {
                modifiers |= Modifiers.@static;
            }

            if ((ma & MethodAttributes.Abstract) != 0) {
                modifiers |= Modifiers.@abstract;
            }

            if ((ma & MethodAttributes.Final) != 0)
                modifiers |= Modifiers.final;

            if ((ma & MethodAttributes.Virtual) != 0) {
                if ((ma & MethodAttributes.NewSlot) != 0) {
                    if ((modifiers & Modifiers.final) != 0) {
                        modifiers &= ~Modifiers.final;
                    } else {
                        modifiers |= Modifiers.@virtual;
                    }
                } else {
                    modifiers |= Modifiers.@override;
                }
            }

            MethodReference result;

            // 创建方法引用。
            if (metaInfo.MemberType == MemberTypes.Constructor) {
                result = new MethodReference(MemberType.constructor);
                result.name = modifiers.hasFlag(Modifiers.@static) ? "@sctor" : "@ctor";
            } else if (metaInfo.IsGenericMethod) {
                Debug.Assert(metaInfo.IsGenericMethodDefinition);
                result = new GenericMethodDefinitionReference(importGenericParameters(metaInfo, metaInfo.GetGenericArguments()));
                result.name = metaInfo.Name;
            } else {
                TokenType type = getOperator(metaInfo.Name);
                // 处理操作符重载。
                if (type != TokenType.eof) {
                    result = new MethodReference(MemberType.@operator);
                    result.name = "@" + type.getName();
                } else {
                    result = new MethodReference(MemberType.method);
                    result.name = metaInfo.Name;

                    // Cannot set to OVERRIDE without full hierarchy checks
                    // this flag indicates that the method could be override
                    // but further validation is needed
                    if ((result.modifiers & Modifiers.@override) != 0) {
                        bool is_real_override = false;
                        if (result.memberType == MemberType.method && result.containerType.baseClass != null) {
                            var btype = result.containerType.baseClass;
                            //if (IsOverrideMethodBaseTypeAccessible(btype)) {
                            //    // var filter = MemberFilter.Method(name, tparams != null ? tparams.Length : 0, parameters, null);
                            //    //  var candidate = MemberCache.FindMember(btype, filter, BindingRestriction.None);

                            //    //
                            //    // For imported class method do additional validation to be sure that metadata
                            //    // override flag was correct
                            //    // 
                            //    // Difference between protected internal and protected is ok
                            //    //
                            //    //const Modifiers conflict_mask = Modifiers.ACCESSIBILITY;
                            //    //if (candidate != null && (candidate.modifiers & conflict_mask) == (mod & conflict_mask) && !candidate.IsStatic) {
                            //    //    is_real_override = true;
                            //    //}
                            //}
                        }

                        if (!is_real_override) {
                            result.modifiers &= ~Modifiers.@override;
                            if ((result.modifiers & Modifiers.final) != 0)
                                result.modifiers &= ~Modifiers.final;
                            else
                                result.modifiers |= Modifiers.@virtual;
                        }
                    }
                }
            }

            result.name = metaInfo.Name;
            result.metaInfo = metaInfo;
            container.addMember(result);

            // 载入返回类型。
            if (result.memberType == MemberType.constructor) {
                result.returnType = PredefinedTypes.@void;
            } else {
                var mi = (MethodInfo)metaInfo;
                result.returnType = importType(mi.ReturnType);
            }

            // 载入参数类型。
            result.parameters = importParameters(metaInfo);

            return result;
        }

        private static TokenType getOperator(string name) {
            if (!name.StartsWith("op_")) {
                return TokenType.eof;
            }
            return TokenType.eof;
        }

        private static MemberType getMemberType(MethodBase metaInfo) {
            if (metaInfo.MemberType == MemberTypes.Constructor) {
                return MemberType.constructor;
            }
            if (metaInfo.Name.StartsWith("op_")) {
                return MemberType.@operator;
            }
            return MemberType.method;
        }

        private static bool IsOverrideMethodBaseTypeAccessible(TypeReference baseType) {
            switch (baseType.modifiers & Modifiers.ACCESSIBILITY) {
                case Modifiers.@public:
                    return true;
                case Modifiers.@private:
                    return false;
                default:
                    // protected
                    // protected internal
                    // 
                    // Method accessibility checks will be done later based on context
                    // where the method is called (CS0122 error will be reported for inaccessible)
                    //
                    return true;
            }
        }

        //
        // Imports System.Reflection parameters
        //
        private static MethodReference.Parameter[] importParameters(MethodBase metaInfo) {
            int varargs = metaInfo != null && (metaInfo.CallingConvention & CallingConventions.VarArgs) != 0 ? 1 : 0;

            var ps = metaInfo.GetParameters();
            var result = new MethodReference.Parameter[ps.Length + varargs];

            for (int i = 0; i < ps.Length; i++) {
                var mp = result[i] = new MethodReference.Parameter();
                var p = ps[i];
                if (p.ParameterType.IsByRef) {
                    if ((p.Attributes & (ParameterAttributes.Out | ParameterAttributes.In)) == ParameterAttributes.Out) {
                        mp.variableType = VariableType.outParameter;
                    } else {
                        mp.variableType = VariableType.refParameter;
                    }
                    mp.type = importType(p.ParameterType.GetElementType());
                } else {
                    mp.type = importType(p.ParameterType);

                    if (i >= ps.Length - 2 && hasAttribute(CustomAttributeData.GetCustomAttributes(p), "System", "ParamArrayAttribute")) {
                        mp.variableType = VariableType.paramsParameter;
                    } else if (p.IsOptional) {
                        // 处理默认值。
                        object value = p.RawDefaultValue;

                        //        object value = p.RawDefaultValue;
                        //        var ptype = types[i];
                        //        if ((p.Attributes & ParameterAttributes.HasDefault) != 0 && ptype.Kind != MemberKind.TypeParameter && (value != null || TypeReference.IsReferenceType(ptype))) {
                        //            if (value == null) {
                        //                default_value = Constant.CreateConstantFromValue(ptype, null, Location2.Null);
                        //            } else {
                        //                default_value = ImportParameterConstant(value);

                        //                if (ptype.IsEnum) {
                        //                    default_value = new EnumConstant((Constant)default_value, ptype);
                        //                }
                        //            }

                        //            var attrs = CustomAttributeData.GetCustomAttributes(p);
                        //            for (int ii = 0; ii < attrs.Count; ++ii) {
                        //                var attr = attrs[ii];
                        //                var dt = attr.Constructor.DeclaringType;
                        //                if (dt.Namespace != CompilerServicesNamespace)
                        //                    continue;

                        //                if (dt.Name == "CallerLineNumberAttribute" && (ptype.BuiltinType == BuiltinTypeSpec.Type.Int || Convert.ImplicitNumericConversionExists(Compiler.BuiltinTypes.Int, ptype)))
                        //                    mod |= Parameter2.Modifier.CallerLineNumber;
                        //                else if (dt.Name == "CallerFilePathAttribute" && Convert.ImplicitReferenceConversionExists(Compiler.BuiltinTypes.String, ptype))
                        //                    mod |= Parameter2.Modifier.CallerFilePath;
                        //                else if (dt.Name == "CallerMemberNameAttribute" && Convert.ImplicitReferenceConversionExists(Compiler.BuiltinTypes.String, ptype))
                        //                    mod |= Parameter2.Modifier.CallerMemberName;
                        //            }
                        //        } else if (value == Missing.Value) {
                        //            default_value = EmptyExpression.MissingValue;
                        //        } else if (value == null) {
                        //            default_value = new DefaultValueExpression(new TypeExpression(ptype, Location2.Null), Location2.Null);
                        //        } else if (ptype.BuiltinType == BuiltinTypeSpec.Type.Decimal) {
                        //            default_value = ImportParameterConstant(value);
                        //        }
                        //    }

                    }
                }
            }

            if (varargs != 0) {
                result[result.Length - 1].variableType = VariableType.argListParameter;
            }

            return result;
        }

        //
        // Returns null when the property is not valid C# property
        //
        public static PropertyReference importProperty(PropertyInfo pi, NamespaceReference container) {


            throw new Unreachable();
            //Modifiers mod = 0;
            //AParametersCollection param = null;
            //TypeReference type = null;
            //if (get != null) {
            //    mod = get.modifiers;
            //    param = get.Parameters;
            //    type = get.ReturnType;
            //}

            //bool is_valid_property = true;
            //if (set != null) {
            //    if (set.ReturnType.Kind != MemberKind.Void)
            //        is_valid_property = false;

            //    var set_param_count = set.Parameters.Count - 1;

            //    if (set_param_count < 0) {
            //        set_param_count = 0;
            //        is_valid_property = false;
            //    }

            //    var set_type = set.Parameters.Types[set_param_count];

            //    if (mod == 0) {
            //        AParametersCollection set_based_param;

            //        if (set_param_count == 0) {
            //            set_based_param = ParametersCompiled.EmptyReadOnlyParameters;
            //        } else {
            //            //
            //            // Create indexer parameters based on setter method parameters (the last parameter has to be removed)
            //            //
            //            var data = new IParameterData[set_param_count];
            //            var types = new TypeReference[set_param_count];
            //            Array.Copy(set.Parameters.FixedParameters, data, set_param_count);
            //            Array.Copy(set.Parameters.Types, types, set_param_count);
            //            set_based_param = new ParametersImported(data, types, set.Parameters.HasParams);
            //        }

            //        mod = set.modifiers;
            //        param = set_based_param;
            //        type = set_type;
            //    } else {
            //        if (set_param_count != get.Parameters.Count)
            //            is_valid_property = false;

            //        if (get.ReturnType != set_type)
            //            is_valid_property = false;

            //        // Possible custom accessor modifiers
            //        if ((mod & Modifiers.ACCESSIBILITY) != (set.modifiers & Modifiers.ACCESSIBILITY)) {
            //            var get_acc = mod & Modifiers.ACCESSIBILITY;
            //            if (get_acc != Modifiers.@public) {
            //                var set_acc = set.modifiers & Modifiers.ACCESSIBILITY;
            //                // If the accessor modifiers are not same, do extra restriction checks
            //                if (get_acc != set_acc) {
            //                    var get_restr = ModifiersExtensions.IsRestrictedModifier(get_acc, set_acc);
            //                    var set_restr = ModifiersExtensions.IsRestrictedModifier(set_acc, get_acc);
            //                    if (get_restr && set_restr) {
            //                        is_valid_property = false; // Neither is more restrictive
            //                    }

            //                    if (get_restr) {
            //                        mod &= ~Modifiers.ACCESSIBILITY;
            //                        mod |= set_acc;
            //                    }
            //                }
            //            }
            //        }
            //    }
            //}

            //PropertyReference spec = null;
            //if (!param.IsEmpty) {
            //    if (is_valid_property) {
            //        var index_name = declaringType.MemberDefinition2.GetAttributeDefaultMember();
            //        if (index_name == null) {
            //            is_valid_property = false;
            //        } else {
            //            if (get != null) {
            //                if (get.IsStatic)
            //                    is_valid_property = false;
            //                if (get.name.IndexOf(index_name, StringComparison.Ordinal) != 4)
            //                    is_valid_property = false;
            //            }
            //            if (set != null) {
            //                if (set.IsStatic)
            //                    is_valid_property = false;
            //                if (set.name.IndexOf(index_name, StringComparison.Ordinal) != 4)
            //                    is_valid_property = false;
            //            }
            //        }

            //        //if (is_valid_property) {
            //        //    spec = new IndexerReference(declaringType, new ImportedParameterMemberDefinition(pi, type, param, this), type, param, pi, mod);
            //        //} else if (declaringType.MemberDefinition2.IsComImport && param.FixedParameters[0].HasDefaultValue) {
            //        //    //
            //        //    // Enables support for properties with parameters (must have default value) of COM-imported types
            //        //    //
            //        //    is_valid_property = true;

            //        //    for (int i = 0; i < param.FixedParameters.Length; ++i) {
            //        //        if (!param.FixedParameters[i].HasDefaultValue) {
            //        //            is_valid_property = false;
            //        //            break;
            //        //        }
            //        //    }
            //        //}
            //    }
            //}

            ////if (spec == null)
            ////    spec = new PropertyReference(MemberKind.Property, declaringType, new ImportedMemberDefinition(pi, type, this), type, pi, mod);

            //if (!is_valid_property) {
            //    spec.IsNotCSharpCompatible = true;
            //    return spec;
            //}

            //if (set != null)
            //    spec.Set = set;
            //if (get != null)
            //    spec.Get = get;

            //return spec;
        }

        static void importTypeParameterTypeConstraints(MemberReference.GenericParameter spec, Type type) {
            //    var constraints = type.GetGenericParameterConstraints();
            //    List<TypeReference> tparams = null;
            //    foreach (var ct in constraints) {
            //        if (ct.IsGenericParameter) {
            //            if (tparams == null)
            //                tparams = new List<TypeReference>();

            //            tparams.Add(CreateType(ct));
            //            continue;
            //        }

            //        var constraint_type = CreateType(ct);
            //        if (constraint_type.IsClass) {
            //            spec.baseClass = constraint_type;
            //            continue;
            //        }

            //        spec.addInterface(constraint_type);
            //    }

            //    if (spec.baseClass == null)
            //        spec.baseClass = Compiler.BuiltinTypes.Object;

            //    if (tparams != null)
            //        spec.TypeArguments = tparams.ToArray();
        }

        static Constant ImportParameterConstant(object value) {
            //
            // Get type of underlying value as int constant can be used for object
            // parameter type. This is not allowed in C# but other languages can do that
            //
            var types = Compiler.BuiltinTypes;
            switch (Type.GetTypeCode(value.GetType())) {
                case TypeCode.Boolean:
                    return new BoolConstant(types, (bool)value, Location2.Null);
                case TypeCode.Byte:
                    return new ByteConstant(types, (byte)value, Location2.Null);
                case TypeCode.Char:
                    return new CharConstant(types, (char)value, Location2.Null);
                case TypeCode.Decimal:
                    return new DecimalConstant(types, (decimal)value, Location2.Null);
                case TypeCode.Double:
                    return new DoubleConstant(types, (double)value, Location2.Null);
                case TypeCode.Int16:
                    return new ShortConstant(types, (short)value, Location2.Null);
                case TypeCode.Int32:
                    return new IntConstant(types, (int)value, Location2.Null);
                case TypeCode.Int64:
                    return new LongConstant(types, (long)value, Location2.Null);
                case TypeCode.SByte:
                    return new SByteConstant(types, (sbyte)value, Location2.Null);
                case TypeCode.Single:
                    return new FloatConstant(types, (float)value, Location2.Null);
                case TypeCode.String:
                    return new StringConstant(types, (string)value, Location2.Null);
                case TypeCode.UInt16:
                    return new UShortConstant(types, (ushort)value, Location2.Null);
                case TypeCode.UInt32:
                    return new UIntConstant(types, (uint)value, Location2.Null);
                case TypeCode.UInt64:
                    return new ULongConstant(types, (ulong)value, Location2.Null);
            }

            throw new NotImplementedException(value.GetType().ToString());
        }

        //protected void Initialize(BuiltinTypes builtin) {
        //    //
        //    // Setup mapping for build-in types to avoid duplication of their definition
        //    //
        //    compiled_types.Add(typeof(object), builtin.Object);
        //    compiled_types.Add(typeof(System.ValueType), builtin.ValueType);
        //    compiled_types.Add(typeof(System.Attribute), builtin.Attribute);

        //    compiled_types.Add(typeof(int), builtin.Int);
        //    compiled_types.Add(typeof(long), builtin.Long);
        //    compiled_types.Add(typeof(uint), builtin.UInt);
        //    compiled_types.Add(typeof(ulong), builtin.ULong);
        //    compiled_types.Add(typeof(byte), builtin.Byte);
        //    compiled_types.Add(typeof(sbyte), builtin.SByte);
        //    compiled_types.Add(typeof(short), builtin.Short);
        //    compiled_types.Add(typeof(ushort), builtin.UShort);

        //    compiled_types.Add(typeof(System.Collections.IEnumerator), builtin.IEnumerator);
        //    compiled_types.Add(typeof(System.Collections.IEnumerable), builtin.IEnumerable);
        //    compiled_types.Add(typeof(System.IDisposable), builtin.IDisposable);

        //    compiled_types.Add(typeof(char), builtin.Char);
        //    compiled_types.Add(typeof(string), builtin.String);
        //    compiled_types.Add(typeof(float), builtin.Float);
        //    compiled_types.Add(typeof(double), builtin.Double);
        //    compiled_types.Add(typeof(decimal), builtin.Decimal);
        //    compiled_types.Add(typeof(bool), builtin.Bool);
        //    compiled_types.Add(typeof(System.IntPtr), builtin.IntPtr);
        //    compiled_types.Add(typeof(System.UIntPtr), builtin.UIntPtr);

        //    compiled_types.Add(typeof(System.MulticastDelegate), builtin.MulticastDelegate);
        //    compiled_types.Add(typeof(System.Delegate), builtin.Delegate);
        //    compiled_types.Add(typeof(System.Enum), builtin.Enum);
        //    compiled_types.Add(typeof(System.Array), builtin.Array);
        //    compiled_types.Add(typeof(void), builtin.Void);
        //    compiled_types.Add(typeof(System.Type), builtin.Type);
        //    compiled_types.Add(typeof(System.Exception), builtin.Exception);
        //    compiled_types.Add(typeof(System.RuntimeFieldHandle), builtin.RuntimeFieldHandle);
        //    compiled_types.Add(typeof(System.RuntimeTypeHandle), builtin.RuntimeTypeHandle);
        //}

        //    public static MemberReference load(MethodInfo methodInfo) {
        //        MethodReference ret = new MethodReference();
        //        ret.modifiers = convertAttributesToModifiers(methodInfo.Attributes);
        //        ret.name = getMemberName(methodInfo.Name);
        //        ret.isImported = true;
        //        ret.methodInfo = methodInfo;

        //        var p = methodInfo.GetParameters();
        //        ret.parameters = new MethodReference.Parameter[p.Length];

        //        for (int i = 0; i < p.Length; i++) {
        //            ret.parameters[i] = loadParameter(p[i]);
        //        }


        //        ret.returnType = getType(methodInfo.ReturnType);

        //        return ret;
        //    }

        //    private static MethodReference.Parameter loadParameter(ParameterInfo parameterInfo) {

        //        var ret = new MethodReference.Parameter();
        //        ret.name = parameterInfo.Name;
        //        ret.type = getType(parameterInfo.ParameterType);
        //        if (parameterInfo.IsIn) {
        //            ret.parameterType = VariableDeclaration.VariableType.inParameter;
        //        } else if (parameterInfo.IsOut) {
        //            ret.parameterType = VariableDeclaration.VariableType.outParameter;
        //        } else if (parameterInfo.IsRetval) {
        //            ret.parameterType = VariableDeclaration.VariableType.refParameter;
        //        } else if (parameterInfo.IsOptional) {
        //            ret.parameterType = VariableDeclaration.VariableType.optionalParameter;
        //        }


        //        return ret;
        //    }

        //    public static MemberReference load(MemberInfo memberInfo) {
        //        switch (memberInfo.MemberType) {
        //            case System.Reflection.MemberTypes.Method:
        //                return load((MethodInfo)memberInfo);
        //            case System.Reflection.MemberTypes.Property:
        //            //	ret = new PropertyReference();
        //            //	break;
        //            case System.Reflection.MemberTypes.Field:
        //            //	ret = new FieldReference();
        //            //	break;
        //            case System.Reflection.MemberTypes.TypeInfo:
        //            //	ret = loadType((Type)memberInfo);
        //            //	break;
        //            default:
        //                MethodReference ret = new MethodReference();
        //                ret.name = getMemberName(memberInfo.Name);
        //                return ret;
        //        }
        //    }

        //    public static void import(TypeReference typeReference) {
        //        foreach (var member in typeReference.typeInfo.GetMembers()) {
        //            typeReference.addMember(load(member));
        //        }
        //    }

        //    public static void load(FieldReference target) {
        //        throw new NotImplementedException();
        //    }

        //    public static void load(MethodReference target) {
        //        throw new NotImplementedException();
        //    }

        //    public static void load(PropertyReference propertyReference) {
        //        throw new NotImplementedException();
        //    }

        public static void importPredefinedTypes(ModuleReference target) {
            //var system = createNamespace(target, "System");
            //    PredefinedTypes.System_Object = importPredefinedType(system, PredefinedTypes.System_Object, typeof(object));

            PredefinedTypes.System_Int32.metaInfo = typeof(int);
            PredefinedTypes.System_Bool.metaInfo = typeof(bool);
            PredefinedTypes.System_String.metaInfo = typeof(string);
            PredefinedTypes.System_Object.metaInfo = typeof(object);
            PredefinedTypes.System_ValueType.metaInfo = typeof(ValueType);
        }

        private static void loadPredefinedType(TypeReference reference, Type type) {
            reference.metaInfo = type;
        }

        #region 工具

        private static string getMemberName(string name) {
            int p = name.IndexOf('`');
            return p >= 0 ? name.Remove(p) : name;
        }

        /// <summary>
        /// 判断指定成员是否是编译器自动生成。
        /// </summary>
        /// <param name="metaInfo">成员的原始信息。</param>
        /// <returns></returns>
        private static bool isCompilerGenerated(MemberInfo metaInfo) {
            return hasAttribute(CustomAttributeData.GetCustomAttributes(metaInfo), "System.Runtime.CompilerServices", "CompilerGeneratedAttribute");
        }

        //
        // Test for a custom attribute type match. Custom attributes are not really predefined globaly 
        // they can be assembly specific therefore we do check based on names only
        //
        private static bool hasAttribute(IList<CustomAttributeData> attributesData, string attrNamespace, string attrName) {
            if (attributesData.Count == 0)
                return false;

            foreach (var attr in attributesData) {
                var dt = attr.Constructor.DeclaringType;
                if (dt.Name == attrName && dt.Namespace == attrNamespace)
                    return true;
            }

            return false;
        }

        #endregion

    }

    /// <summary>
    /// 表示解析的标记位。
    /// </summary>
    enum ImportedTypeFlags {

        /// <summary>
        /// 标记当前类型的泛型形参已初始化。
        /// </summary>
        genericParametersInited = 1 << 1,

        /// <summary>
        /// 标记当前类型的子成员已初始化。
        /// </summary>
        childMembersInited = 1 << 5,

    }

    /// <summary>
    /// 表示一个导入的类型。
    /// </summary>
    public sealed class ImportedTypeReference : TypeReference {

        /// <summary>
        /// 初始化 <see cref="ImportedTypeReference"/> 类的新实例。
        /// </summary>
        /// <param name="memberType">成员的类型。</param>
        public ImportedTypeReference(MemberType memberType)
            : base(memberType) {

        }

        /// <summary>
        /// 当前类型解析标记。
        /// </summary>
        ImportedTypeFlags _flags;

        /// <summary>
        /// 获取当前容器内的所有成员。
        /// </summary>
        public sealed override Dictionary<string, MemberReference> members {
            get {
                if ((_flags & ImportedTypeFlags.childMembersInited) == 0) {
                    _flags |= ImportedTypeFlags.childMembersInited;
                    AssemblyImporter.importMembers(this);
                }
                return base.members;
            }
        }

    }

    /// <summary>
    /// 表示一个导入的泛型类型。
    /// </summary>
    public sealed class ImportedGenericTypeDefinitionReference : GenericTypeDefinitionReference {

        /// <summary>
        /// 当前类型解析标记。
        /// </summary>
        ImportedTypeFlags _flags;

        /// <summary>
        /// 获取当前成员的泛型形参。
        /// </summary>
        /// <remarks>
        /// 如果当前类型是泛型实体或泛型定义的非泛型内嵌类，则返回 null。
        /// </remarks>
        public override GenericParameter[] genericParameters {
            get {
                if ((_flags & ImportedTypeFlags.genericParametersInited) == 0) {
                    _flags |= ImportedTypeFlags.genericParametersInited;
                    base.typeArguments = AssemblyImporter.importGenericParameters(metaInfo, metaInfo.GetGenericArguments());
                }
                return base.genericParameters;
            }
        }

        /// <summary>
        /// 获取当前容器内的所有成员。
        /// </summary>
        public sealed override Dictionary<string, MemberReference> members {
            get {
                if ((_flags & ImportedTypeFlags.childMembersInited) == 0) {
                    _flags |= ImportedTypeFlags.childMembersInited;
                    AssemblyImporter.importMembers(this);
                }
                return base.members;
            }
        }

        /// <summary>
        /// 创建一个新的泛型定义。
        /// </summary>
        /// <param name="memberType">成员的类型。</param>
        public ImportedGenericTypeDefinitionReference(MemberType memberType)
            : base(memberType, null) {

        }

    }

    /// <summary>
    /// 表示一个丢失的模块引用。
    /// </summary>
    public sealed class MissingModuleReference : ModuleReference {

    }

}